package dev.bong.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import dev.bong.dto.ScheduleDTO;
import dev.bong.dto.SemesterDTO;
import dev.bong.dto.UserDTO;
import dev.bong.dto.UserPageQueryDTO;
import dev.bong.mapper.*;

import dev.bong.pojo.entity.*;
import dev.bong.pojo.result.PageResult;

import dev.bong.service.AdminService;
import dev.bong.utils.Md5Util;
import dev.bong.utils.ThreadLocalUtil;
import dev.bong.vo.*;
import dev.bong.vo.schedule.Course;
import dev.bong.vo.schedule.LabSchedule;
import dev.bong.vo.schedule.ScheduleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.Year;
import java.util.*;


/**
 * @author: bong~
 * @description: TODO
 * @date: 2024/4/10 20:38
 * @version: 1.0
 */

@Service
@Slf4j
public class AdminServiceImpl implements AdminService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SemesterMapper semesterMapper;

    @Autowired
    private LabApplyMapper labApplyMapper;

    @Autowired
    private LabMapper labMapper;

    @Autowired
    private LabRegisterMapper labRegisterMapper;

    @Autowired
    private ClassScheduleMapper classScheduleMapper;


//    (1) 学期管理
//    - 列出平台已经有的学期
//    - 添加新的学期
//    - 设置平台的当前学期

    @Override
    public String getCurrentSemester() {
        return semesterMapper.getCurrentSemester();
    }

    @Override
    public List<SemesterVo> getSemesterList() {

        List<Semester> oriList=semesterMapper.getSemesterList();
        List<SemesterVo> ans=new ArrayList<>();
        for(Semester semester:oriList){
            SemesterVo vo=
                    new SemesterVo(semester.getId(),semester.getSemester(),semester.getSemesterStatus(),semester.getWeekNum());
            ans.add(vo);
        }
        return ans;

    }

    @Override
    public void addSemester(SemesterDTO dto) {
        Semester semester=Semester.builder()
                .semester(dto.getSemester())
                .semesterStatus(dto.getSemesterStatus())
                .weekNum(dto.getWeekNum())
                .build();
        //Semester semester=SemesterDTO.toSemester(dto);
        semesterMapper.addSemester(semester);


    }

    @Override
    public void setCurrentSemester(Integer id) {
        semesterMapper.delPreSemester();
        semesterMapper.setCurrentSemester(id);

    }


    @Override
    public User findByUserAccount(String account) {
        return userMapper.getUserByUserAccount(account);
    }

    @Override
    public void register(UserDTO userDTO) {

        User user=User.builder()
                .roleId(userDTO.getRoleId())
                .userName(userDTO.getUserName())
                .userAccount(userDTO.getUserAccount())
                .userPassword(userDTO.getUserPassword())
                .major(userDTO.getMajor())
                .className(userDTO.getClassName())
                .professionalTitle(userDTO.getProfessionalTitle())
                .build();

        String oriPassword=user.getUserPassword();
        String md5String= Md5Util.getMD5String(oriPassword);
        user.setUserPassword(md5String);
        userMapper.addUser(user);

    }

    @Override
    public void updateUser(UserDTO dto,Integer userId) {



        User user=User.builder()
                .id(userId)
                .roleId(dto.getRoleId())
                .userName(dto.getUserName())
                .userAccount(dto.getUserAccount())
                .userPassword(dto.getUserPassword())
                .major(dto.getMajor())
                .className(dto.getClassName())
                .professionalTitle(dto.getProfessionalTitle())
                .build();
        userMapper.updateUser(user);


    }

    @Override
    public PageResult pageQuery(UserPageQueryDTO dto) {

        int page= dto.getPage();
        int  pageSize= dto.getPageSize();
        PageHelper.startPage(page,pageSize);

        Page<UserVo> pages= userMapper.pageQuery(dto);

        long total=pages.getTotal();
        List<UserVo> records=pages.getResult();

        return new PageResult(total,records);
    }

    @Override
    public void deleteUser(List<Integer> ids) {
        userMapper.deleteUser(ids);
    }

    @Override
    public void resetPassword(List<Integer> ids,String password) {

        String newPass=Md5Util.getMD5String(password);
        userMapper.resetPassword(ids,newPass);
    }

    @Override
    public List<RegisterVO> getRegisterList() {

        Map<String,Object> map=ThreadLocalUtil.get();
        String semester=(String)map.get("semester");

        List<LabRegister> list=labRegisterMapper.getRegisterList();
        List<RegisterVO> ans=new ArrayList<>();


        for(LabRegister tmp:list){
            String teacherName=userMapper.getNameById(tmp.getTeacherId());
            RegisterVO vo= RegisterVO.builder()
                            .id(tmp.getId())
                            .semester(tmp.getSemester())
                            .registerStatus(tmp.getRegisterStatus())
                            .labType(tmp.getLabType())
                            .className(tmp.getClassName())
                            .studentNum(tmp.getStudentNum())
                            .studentClass(tmp.getStudentClass())
                            .weekStart(tmp.getWeekStart())
                            .weekEnd(tmp.getWeekEnd())
                            .section(tmp.getSection())
                            .teacherName(teacherName)
                            .build();
            ans.add(vo);
        }
        return ans;

    }

    @Override
    public void addSchedule(ScheduleDTO dto) throws Exception{

        Integer registerId=dto.getRegisterId();

        LabRegister labRegister=labRegisterMapper.getRegisterById(registerId);
        Integer teacherId;
        try{
            teacherId =labRegister.getTeacherId();
        }catch (Exception e){
            throw new RuntimeException("未指定登记申请id");
        }


        Map<String,Object> map= ThreadLocalUtil.get();
        Integer userId=(Integer) map.get("userId");
        LocalDateTime now=LocalDateTime.now();

        labRegisterMapper.updateRegisterStatusById(registerId,1,userId,now);

        ClassSchedule classSchedule=ClassSchedule.builder()
                .teacherId(teacherId)
                .semester(dto.getSemester())
                .className(dto.getClassName())
                .labType(dto.getLabType())
                .labNumber(dto.getLabNumber())
                .weekStart(dto.getWeekStart())
                .weekEnd(dto.getWeekEnd())
                .weekDay(dto.getWeekDay())
                .section(dto.getSection())
                .studentClass(dto.getStudentClass())
                .build();


        classScheduleMapper.addSchedule(classSchedule);
    }




    @Override
    public List<ApplyVo> getBorrowList() {

        List<LabApply> list=labApplyMapper.selectApplyList();

        List<ApplyVo> ans=new ArrayList<>();

        Map<Integer,String> map=new HashMap<>();


        for(LabApply tmp:list){
            String studentName=userMapper.getNameById(tmp.getStudentId());
            ApplyVo vo=ApplyVo.builder()
                    .studentName(studentName)
                    .id(tmp.getId())
                    .semester(tmp.getSemester())
                    .weeks(tmp.getWeeks())
                    .section(tmp.getSection())
                    .labNumber(tmp.getLabNumber())
                    .applyReason(tmp.getApplyReason())
                    .applyTime(tmp.getApplyTime())
                    .applyStatus(tmp.getApplyStatus())
                    .build();
            ans.add(vo);
        }
        return ans;


    }

    @Override
    public void approvalBorrow(Integer applyId, Integer applyStatus) {
        labApplyMapper.approvalBorrow(applyId,applyStatus);
    }

    @Override
    public List<ScheduleVo> getScheduleList() {


        String semester=semesterMapper.getCurrentSemester();

        List<ClassSchedule> list=classScheduleMapper.selectListBySemester(semester);


        List<Lab> labList=labMapper.getLabList();
        System.out.println(labList.toString());

        Map<String,Integer> labOrder=new HashMap<>();
        Set<String> labSet=new HashSet<>();
        for(int i=0;i<labList.size();i++){
            labOrder.put(labList.get(i).getLabNumber(),i);
            labSet.add(labList.get(i).getLabNumber());
        }

        System.out.println(labOrder);
        List<ScheduleVo> ans=new ArrayList<>();

        ScheduleVo vo1=new ScheduleVo(semester,"星期一");
        ScheduleVo vo2=new ScheduleVo(semester,"星期二");
        ScheduleVo vo3=new ScheduleVo(semester,"星期三");
        ScheduleVo vo4=new ScheduleVo(semester,"星期四");
        ScheduleVo vo5=new ScheduleVo(semester,"星期五");

        ans.add(vo1);
        ans.add(vo2);
        ans.add(vo3);
        ans.add(vo4);
        ans.add(vo5);

        for(ScheduleVo vo:ans){

            for(int i=0;i<labList.size();i++){

                String type=labList.get(i).getLabType();
                String number=labList.get(i).getLabNumber();

                LabSchedule labSchedule=new LabSchedule(type,number);

                Course course1=new Course("1-2");
                Course course2=new Course("3-5");
                Course course3=new Course("6-7");
                Course course4=new Course("8-9");
                Course course5=new Course("10-12");
                Course course6=new Course("13-15");

                labSchedule.getCourseList().add(course1);
                labSchedule.getCourseList().add(course2);
                labSchedule.getCourseList().add(course3);
                labSchedule.getCourseList().add(course4);
                labSchedule.getCourseList().add(course5);
                labSchedule.getCourseList().add(course6);

                vo.getLabList().add(labSchedule);

            }

        }
        arrange(ans,list,labOrder,labSet);

        return ans;
    }




    private void arrange(List<ScheduleVo> ans,List<ClassSchedule> list,Map<String,Integer> labOrder,Set<String> labSet){

        Map<String, Integer> weekOrder = new HashMap<String, Integer>() {{
            put("星期一", 0);
            put("星期二", 1);
            put("星期三", 2);
            put("星期四", 3);
            put("星期五", 4);
        }};

        Map<String, Integer> sectionOrder = new HashMap<String, Integer>() {{
            put("1-2",0);
            put("3-5",1);
            put("6-7",2);
            put("8-9",3);
            put("10-12",4);
            put("13-15",5);
        }};
        for(ClassSchedule tmp:list){

            System.out.println(tmp);

            String weekDay=tmp.getWeekDay();
            String labNumber=tmp.getLabNumber();
            String section= tmp.getSection();



            if(labSet.contains(labNumber)){
                Integer weekIndex=weekOrder.get(weekDay);
                Integer labIndex=labOrder.get(labNumber);
                Integer sectionIndex=sectionOrder.get(section);


                Course course=ans.get(weekIndex).getLabList().get(labIndex).getCourseList().get(sectionIndex);
                course.setTeacherName(userMapper.getNameById(tmp.getTeacherId()));
                course.setClassName(tmp.getClassName());
                course.setStudentClass(tmp.getStudentClass());
                course.setWeekStart(tmp.getWeekStart());
                course.setWeekEnd(tmp.getWeekEnd());
            }






        }

    }

    @Override
    public List<LabVo> getLabList() {
        List<Lab> list=labMapper.getLabList();
        List<LabVo> ans=new ArrayList<>();

        for(Lab tmp:list){

            String experimenterName=userMapper.getNameById(tmp.getExperimenterId());
            LabVo labVo=LabVo.builder()
                    .labName(tmp.getLabName())
                    .LabDeviceNum(tmp.getLabDeviceNum())
                    .labType(tmp.getLabType())
                    .labNumber(tmp.getLabNumber())
                    .experimenterName(experimenterName)
                    .build();
            ans.add(labVo);
        }
        return ans;
    }


}
